package br3akr.DeadlyDinnerParty.Server.Actions;

import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Timer;
import java.util.TimerTask;

import br3akr.DeadlyDinnerParty.Server.Engine.Session;
import br3akr.DeadlyDinnerParty.Server.Engine.TimedActionTask;
import br3akr.DeadlyDinnerParty.Server.Exceptions.DeadlyDinnerPartyException;
import br3akr.DeadlyDinnerParty.Server.World.Area;
import br3akr.DeadlyDinnerParty.Server.World.Chest;
import br3akr.DeadlyDinnerParty.Server.World.Exit;
import br3akr.DeadlyDinnerParty.Server.World.GameCharacter;
import br3akr.DeadlyDinnerParty.Server.World.Exit.ExitStatus;

public class PickAction extends Action implements TimerAction {
	boolean actionComplete;
    private ActionResponse actionResponse;
	private static final int START  = 1;
	private static final int CONTINUING = 2;
	private static final int COMPLETE = 3;
    public static final Set<String> keywords;
    private int curStep = START;
    private Area pickingLocation = null;
    private Area pickingExitLocation = null;
    private Exit pickingExit = null;
    private Chest pickingChest = null;
    private GameCharacter pickingHandcuffsCharacter = null;
    private TimerTask task;
    private String currentDescription;
    
	static
	{
		Set<String>tempKeywords = new HashSet<String>();
		tempKeywords.add("Pick");
		tempKeywords.add("Pi");
		keywords = Collections.unmodifiableSet(tempKeywords);
	}
    
    public PickAction() {
        super("Pick", false);
    }
    
    public ActionResponse doAction(String action, Session session) throws DeadlyDinnerPartyException {
    	if (curStep == START) {
			if (action == null) {
				actionComplete = true;
				throw new DeadlyDinnerPartyException ("No action found.");
			}
			if (session == null) {
				actionComplete = true;
				throw new DeadlyDinnerPartyException ("No session found.");
			}
			
	    	StringTokenizer tokenizedAction = new StringTokenizer(action);
	    	String param1 = null;
	    	tokenizedAction.nextToken(); // We don't need the first token.
	    	
	    	if (tokenizedAction.hasMoreTokens()) {
	    		param1 = tokenizedAction.nextToken();
	    	}
	    	
			GameCharacter actor = session.getCharacter();
			
			if (actor == null) {
				actionComplete = true;
				throw new DeadlyDinnerPartyException ("No character found for your session.");
			}
	    	
	    	actionResponse = new ActionResponse();
	    	actionResponse.setActingCharacter(session.getCharacter());
	    	Area location = session.getCharacter().getLocation();
	    	Set<GameCharacter> localOnlookers = location.getAreaOnlookers(session.getCharacter(), null);
	    	Set<GameCharacter> exitOnlookers = null;
	    	Area exitLocation = null;
	    	Exit exit = null;
	    	Chest chest = null;
	
			exit = location.getExit(Exit.getDirection(param1));
	    	
	    	if (exit == null) {
	    		chest = location.getChest(param1);
	    		
	    		if (chest == null) {
	    			actionComplete = true;
	    			throw new DeadlyDinnerPartyException ("You must pick either a chest, or an exit. " + param1 + " is neither.");
	    		}
	    	}
	    	
	    	if (exit != null) {
		    	exitLocation = exit.getExitArea(location);
		    	
		    	if (exitLocation == null) {
		    		actionComplete = true;
		    		throw new DeadlyDinnerPartyException ("There is no exit " + exit);
		    	}
		    	pickingLocation = location;
		    	pickingExitLocation = exitLocation;
		    	pickingExit = exit;
		    	exitOnlookers = exitLocation.getAreaOnlookers(session.getCharacter(), null);
		    	actionResponse.addAffectedArea(location);
		    	actionResponse.addAffectedArea(exitLocation);
				actionResponse.addOnlookers(localOnlookers, session.getCharacter().getName() + " begins picking the door " + exit + " to " + exitLocation.getName() + ".");
				actionResponse.addOnlookers(exitOnlookers, "The handle of the door " + exit.getExitDirection(exitLocation) + " to " + location.getName() + " rattles. Someone is trying to open it.");
				actionResponse.setActingCharacterDescription("You begin picking the lock " + exit + " to " + exitLocation.getName() + ".");
				currentDescription =  session.getCharacter().getName() + " is here picking the lock of the door " + exit + " to " + exitLocation.getName() + ".";
	    	} else {
	    		pickingChest = chest;
		    	actionResponse.addAffectedArea(location);
				actionResponse.addOnlookers(localOnlookers, session.getCharacter().getName() + " begins picking " + chest.getName() + "'s lock.");
				actionResponse.setActingCharacterDescription("You begin picking " + chest.getName() + "'s lock.");
			}
			task = new TimedActionTask(session, this);
			Timer timer = new Timer();
			timer.schedule(task, 5000);
	    	curStep = CONTINUING;
    	} else if (curStep == CONTINUING) {
    		if (action.equalsIgnoreCase("QUIT") || action.equalsIgnoreCase("Q") || action.equalsIgnoreCase("STOP") || action.equalsIgnoreCase("DONE")) {
    			actionComplete = true;
    			throw new DeadlyDinnerPartyException ("You quit picking the lock.");
    		}
    		throw new DeadlyDinnerPartyException ("You're still picking the lock!");
    	} else if (curStep == COMPLETE) {
    		actionComplete = true;
    		actionResponse = new ActionResponse();
    		if (pickingLocation != null) {
    			actionResponse.addAffectedArea(pickingExitLocation);
    			actionResponse.addAffectedArea(pickingLocation);
    			Set<GameCharacter> localOnlookers = pickingLocation.getAreaOnlookers(session.getCharacter(), null);
    			Set<GameCharacter> exitOnlookers = pickingExitLocation.getAreaOnlookers(session.getCharacter(), null);
    			actionResponse.addOnlookers(localOnlookers, "Somone picked da lock!");
    			actionResponse.addOnlookers(exitOnlookers, "Somone picked da lock!");
    			actionResponse.setActingCharacter(session.getCharacter());
    			actionResponse.setActingCharacterDescription("You picked da lock!");
				Exit.ExitStatus curExitStatus = pickingExit.getStatus();
				Exit.ExitDirections exitDir = pickingExit.getExitDirection(pickingLocation);
				if (curExitStatus == null) {
					throw new DeadlyDinnerPartyException("There is no door to the " + exitDir + " to unlock.");
				}
				if (curExitStatus == ExitStatus.OPEN || curExitStatus == ExitStatus.CLOSED) {
					throw new DeadlyDinnerPartyException("The door to the " + exitDir + " is already unlocked.");
				}
				if (curExitStatus == ExitStatus.BASHED) {
					throw new DeadlyDinnerPartyException("The door to the " + exitDir + " is already bashed open.");
				}
				if (curExitStatus == ExitStatus.LOCKED) {
					pickingExit.setStatus(ExitStatus.CLOSED);
				}
    		} else if (pickingChest != null) {
    			
    		} else if (pickingHandcuffsCharacter != null) {
    			
    		}
    	}
        return actionResponse;
    }
	
    public ActionResponse getActionResponse() {
		return actionResponse;
	}

	public boolean isComplete() {
		return actionComplete;
	}
    
    public Set<String> getKeywords() {
        return keywords;
    }

	public void nextStep() {
		if (curStep == CONTINUING) {
			curStep = COMPLETE;
		}
		
		if (curStep == COMPLETE) {
			actionComplete = true;
		}
	}

	@Override
	public long timeLeft() {
		return task.scheduledExecutionTime() - (new Date()).getTime();
	}

	@Override
	public String getCurrentDescription() {
		return currentDescription;
	}
}